/**
* @project admin-go-api
* @name upload
* @descriptions 文件上传服务
* @author 寒锋
* @date 2023-12-21 14:16:50
 */

package service

import (
	"admin-go-api/common/config"
	"admin-go-api/common/response"
	"admin-go-api/common/util"
	"admin-go-api/constants"
	"fmt"
	"github.com/gin-gonic/gin"
	"path"
	"strconv"
	"strings"
	"time"
)

type IUploadService interface {
	Upload(c *gin.Context)
}

type UploadServiceImpl struct {
}

// Upload 文件上传
func (u UploadServiceImpl) Upload(c *gin.Context) {
	file, err := c.FormFile("file")
	if err != nil {
		response.Failed(c, int(constants.ApiCode.FileUploadError), constants.ApiCode.GetMessage(constants.ApiCode.FileUploadError))
		return
	}
	fileHeader := file.Header
	// 验证文件mimeType 类型
	mimeTypeArr := strings.Split(config.Config.ImageSettings.FileMimeType, ",")
	if !util.InArray(fileHeader["Content-Type"][0], mimeTypeArr) {
		response.Failed(c, int(constants.ApiCode.FileUploadError), "上传文件类型错误")
		return
	}
	// 验证文件后缀名
	suffix := path.Ext(file.Filename)
	suffixArr := strings.Split(config.Config.ImageSettings.FileSuffix, ",")
	if !util.InArray(strings.Trim(suffix, "."), suffixArr) {
		response.Failed(c, int(constants.ApiCode.FileUploadError), "无法识别此文件")
		return
	}
	// 验证文件大小
	fileSize := int64(config.Config.ImageSettings.FileSize * 1024 * 1024)
	if file.Size > fileSize {
		response.Failed(c, int(constants.ApiCode.FileUploadError), "文件大小超出限制")
		return
	}
	// 生成随机文件名
	now := time.Now()
	fileName := strconv.Itoa(now.Nanosecond()) + suffix
	// 文件存储目录
	dirPath := fmt.Sprintf("%s%s%s%s",
		config.Config.ImageSettings.UploadDir,
		fmt.Sprintf("%04d", now.Year()),
		fmt.Sprintf("%02d", now.Month()),
		fmt.Sprintf("%02d", now.Day()))
	// 创建目录
	err = util.CreateDir(dirPath)
	if err != nil {
		response.Failed(c, int(constants.ApiCode.FileUploadError), "文件目录创建失败")
		return
	}
	// 完成的文件地址
	fullPath := fmt.Sprintf("%s/%s", dirPath, fileName)
	// 保存文件到磁盘
	err = c.SaveUploadedFile(file, fullPath)
	if err != nil {
		response.Failed(c, int(constants.ApiCode.FileUploadError), "文件上传失败")
		return
	}
	data := map[string]interface{}{"url": fmt.Sprintf("%s/%s", config.Config.ImageSettings.ImageHost, fullPath)}
	response.Success(c, data)
}

var uploadService = UploadServiceImpl{}

func UploadService() IUploadService {
	return &uploadService
}
